iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Software Development

或躍在淵的CAE: 讓咱們用Python會一會ANSA + LS-DYNA系列 第 20

[Day20] - Box Drop Project精進計畫(12) - 部署於Streamlit Cloud,可於遠端產生config檔並上傳至Linode Object Storage

  • 分享至 

  • xImage
  •  

[Day19]我們成功透過Streamlit建立了config檔,並儲存於本機端。但是當我們想要將此config分享給其他人,又或者想要於其他電腦使用這個config,該怎麼做呢?

我們的作法是放在一個自己可控制的下載空間,Linode Object Storage(S3-compatible)是我們推薦的解決方案。

Linode Object Storage

  • Linode中建立一個名為ithome2022-st-s3Bucket,地點選擇ap-south-1的新加坡,此Bucket的網址為ithome2022-st-s3.ap-south-1.linodeobjects.com
  • 針對這個Bucket,建立一組aws_access_key_idaws_secret_access_key並將其輸入至.streamlit/secrets.toml。另外再建立endpoint_url = "https://ap-south-1.linodeobjects.com"bucket_name = "ithome2022-st-s3"兩個secret

整個.streamlit/secrets.toml看起來會像是:

aws_access_key_id = "0aa818b68c0145c38ac6" # fake
aws_secret_access_key = "30427f2bab4b4d87993f78c6e6911a885417c4ab" # fake
endpoint_url = "https://ap-south-1.linodeobjects.com"
bucket_name = "ithome2022-st-s3"

S3 Wrapper

  • 可以將st.secrets當作一個字典,透過它取得儲存於.streamlit/secrets.tomlsecrets
  • 透過pydantic建立一個S3Credentials model將這些secret存為一個pydantic model
  • 建立一個MyS3來呼叫boto3產生client,供後續Streamlit使用。
  • 透過get_my_s3, 將S3Credentials傳給MyS3後回傳。
#st_app.py
import boto3
import streamlit as st
from pydantic import BaseModel


class S3Credentials(BaseModel):
    aws_access_key_id: str
    aws_secret_access_key: str
    endpoint_url: str


class MyS3:
    def __init__(self, s3_credentials):
        self.s3_credentials = s3_credentials

    def get_s3_client(self):
        if hasattr(self, 's3_client'):
            return self.s3_client
        self.s3_client = boto3.client('s3', **self.s3_credentials)
        return self.s3_client


def get_my_s3():
    s3_credentials = S3Credentials(aws_access_key_id=st.secrets['aws_access_key_id'],
                                   aws_secret_access_key=st.secrets['aws_secret_access_key'],
                                   endpoint_url=st.secrets['endpoint_url'])
    return MyS3(s3_credentials=s3_credentials.dict())

Streamlit

  • 透過get_my_s3及其get_s3_client function取得s3_client
  • 透過json.dumps寫出data並進行'utf-8'encoding後放入BytesIO。請注意,這邊需要做s.seek(0),可參考stackoverflow的文章。
  • 透過boto3.clientupload_fileobj function,將config上傳至Linode Object Storage。關於權限部份,我們於ExtraArgsACL設定為public-read(預設是private),這樣就可以供每個人下載了。
#st_app.py
            bucket_name = st.secrets['bucket_name']
            my_s3 = get_my_s3()
            s3_client = my_s3.get_s3_client()

            s = BytesIO(json.dumps(data).encode('utf-8'))
            s.seek(0)

            filename = 'input_data.json'
            s3_client.upload_fileobj(Fileobj=s,
                                     Bucket=st.secrets['bucket_name'],
                                     Key=filename,
                                     ExtraArgs={'ACL': 'public-read'})

            now = datetime.now().strftime('%Y%m%d_%H%M%s')
            st.info(
                f'{filename} is uploaded to Bucket[{bucket_name}] at {now}.')

Streamlit Cloud

Streamlit Cloud 現在為一免費部署服務,其限制如下:

Services Limits
Resources per app 1 GB
Private apps 1 app
Public apps Unlimited
Users 3 users

我們選擇用GitHub Account來註冊Streamlit,如果日後要部署Private App會比較方便。

行前準備

在部署之前,我們可以利用streamlit Cloudsecrets management來製造一個需要登入usernamepassword,才能使用App的入口。

Streamlit很貼心地提供了可以複製貼上的check_password function。有了這個function後,我們可以在一進入App,就先檢查usernamepassword,如果正確才會顯示出Form

#st_app.py
def check_password():
    ...

def main():
    if check_password():
        ...

加上原先位於.streamlit/secrets.toml的四個環境變數,我們的App Settings中的Secrets欄位會看起來像:

aws_access_key_id = "0aa818b68c0145c38ac6" # fake
aws_secret_access_key = "30427f2bab4b4d87993f78c6e6911a885417c4ab" # fake
endpoint_url = "https://ap-south-1.linodeobjects.com"
bucket_name = "ithome2022-st-s3"

[passwords]
"jrycw@example.com" = "ithome2022" # fake

這樣一來,我們部署於Streamlit Cloud就不再需要依靠.streamlit/secrets.toml這個檔案來提供secrets了。

部署介面

我們選擇Public apps,其部署介面如下:
deployment

部署過程或部署完畢後,可以點選右下角的Manage app觀看log或做更多操控。
manage-app

例如可以點選Analytics,觀看Streamlit Cloud提供的統計分析(此為示意圖,非本app真實數據):
analytics

ANSA

此處我們新建一個env.py來儲存s3_url,並透過urllib去讀入config檔,並傳給main

請注意,如果遇到如[Day02 安裝VSCode]的問題,可以加上ssl._create_default_https_context = ssl._create_unverified_context來解決(後果請自行評估...)。

#box_drop.py
    ssl._create_default_https_context = ssl._create_unverified_context
    with urllib.request.urlopen(s3_url) as resp:
        config = json.load(resp)
    main(config)

備註

我們將[Day08]的精進大綱稍微更動,將原先預計於[Day20]~[Day21]濃縮於今天,原因是我們決定於明天分享如何使用Streamlit來搭配Prefect,請大家拭目以待。

Code


上一篇
[Day19] - Box Drop Project精進計畫(11) - 使用Streamlit於本機端產生config檔
下一篇
[Day21] - Box Drop Project精進計畫(13) - 使用Streamlit Cloud搭配Prefect Cloud一起Build個LS-DYNA SaaS
系列文
或躍在淵的CAE: 讓咱們用Python會一會ANSA + LS-DYNA30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言